/**
 * Created by user on 2017/12/21.
 */
/**
 task:{
  type:
  timestamp:
  seq_time:
  data:
  callback:
}

 task.type  就是   message type,
 对于每一个类型的消息，都必须有一个事件处理函数。
 事件处理函数的格式为    do + 事件类型(大写) + Event
 do_START_Event(msg, endCallback);
 */


/**
 * DELAY_MESSAGE_TYPE 执行需要时间，执行期间将其他消息hold住
 * INSTANT_MESSAGE_TYPE 表示立刻执行，不被delay消息所牵绊的
 * 第三种类型即普通类型
 */
import Type from './Type'
import GlobalTime from './GlobalTime'
const INSTANT_MESSAGE_TYPE = [
  Type.COMMON_TYPE.COMMON_DM_TEXT,
  Type.COMMON_TYPE.COMMON_GET_USERS,
  Type.COMMON_TYPE.COMMON_START_RECORD,
  Type.COMMON_TYPE.COMMON_STOP_RECORD
]
class MessageCenter {
  constructor() {
    this.start_time = null
    this.task_list = []
    this.stopFlag = false
    this.count = 0
    this.instance_list = []
  }
  reset() {
    this.task_list = []
    this.stopFlag = false
    this.count = 0
    this.instance_list = []
  }
  cloneObj(obj) {
    var o
    if (typeof obj === "object") {
      if (obj === null) {
        o = null
      } else {
        if (obj instanceof Array) {
          o = []
          for (var i = 0, len = obj.length; i < len; i++) {
            o.push(this.cloneObj(obj[i]))
          }
        } else {
          o = {}
          for(var k in obj){
            o[k] = this.cloneObj(obj[k])
          }
        }
      }
    } else {
      o = obj
    }
    return o
  }
  setQa(bool) {
    this.qaFlag = bool
  }
  setStartTime(time) {
    this.start_time = time
  }
  getStartTime() {
    return this.start_time
  }
  callback = () => {}
  setCallback(callback){
    this.callback = callback
  }
  stop() {
    this.stopFlag = true
  }
  start() {
    if (!this.start_time) {
      this.start_time = GlobalTime.getGlobalTime()
    }
    setInterval(() => {
      this.checkTask()
    }, 500)
  }
  addMessage(msg) {
    var m = this.cloneObj(msg)
    m.doing = false
    m.done = false
    m.count = this.count
    this.count ++
    if (INSTANT_MESSAGE_TYPE.indexOf(m.type) < 0) {
      this.task_list.push(m)
    } else {
      this.instance_list.push(m)
    }
  }
  checkTask() {
    if (this.stopFlag) {
      return
    }
    var self = this
    var now = GlobalTime.getGlobalTime()
    var diff = now - this.start_time

    var last = this.getMaxDoneTask()
    var next = this.getMinUndoneTask()
    var nextInstant = this.getMinInstantTask()

    function checkNormalTask() {
      if (!next) {
        return
      }
      if (next.doing) {
        return
      }
      if (!last) {
        if (diff > next.seq_time) {
          self.oneTask(next)
        }
        return
      }
      if (diff - last.seq_time > next.seq_time - last.seq_time) {
        self.oneTask(next)
        return
      }
    }
    function checkInstantTask() {
      if (!nextInstant) {
        return
      }
      if (nextInstant.doing) {
        return
      }
      self.oneTask(nextInstant)
    }

    checkNormalTask()
    checkInstantTask()
  }
  oneTask(current_task) {
    var diff = GlobalTime.getGlobalTime() - this.start_time
    current_task.do_time = diff
    current_task.doing = true
    if (current_task.isDelay) {
      current_task.doing = true
      this.callback(current_task.type, current_task, ()=>{
        current_task.done = true
        current_task.done_time =  GlobalTime.getGlobalTime() - this.start_time
        this.deleteDoneTask(current_task)
      })
    } else {
      this.callback(current_task.type, current_task, () => {})
      current_task.done = true
      current_task.done_time =  GlobalTime.getGlobalTime() - this.start_time
      this.deleteDoneTask(current_task)
    }
  }
  deleteDoneTask(task) {
    if (INSTANT_MESSAGE_TYPE.indexOf(task.type) < 0) {
      for (let key in this.task_list) {
        if (this.task_list[key].count == task.count) {
          this.task_list.splice(key, 1);
          break
        }
      }
    } else {
      for (let key in this.instance_list) {
        if(this.instance_list[key].count == task.count){
          this.instance_list.splice(key, 1)
          break
        }
      }
    }
  }
  getMaxDoneTask() {
    var seq_time = 0
    var task = null
    for (var i in this.task_list) {
      var current_task = this.task_list[i]
      if (INSTANT_MESSAGE_TYPE.indexOf(current_task.type) >= 0) {
        continue
      }
      if (current_task.done) {
        if (current_task.done_time > seq_time) {
          seq_time = current_task.done_time
          task = current_task
        }
      }
    }
    return task
  }
  getMinUndoneTask() {
    var seq_time = 99999999999999
    var task = null
    for (var i in this.task_list) {
      var current_task = this.task_list[i]
      if (INSTANT_MESSAGE_TYPE.indexOf(current_task.type) >= 0) {
        continue
      }
      if (!current_task.done) {
        if (current_task.seq_time < seq_time) {
          seq_time = current_task.seq_time
          task = current_task
        }
      }
    }
    return task
  }
  getMinInstantTask(){
    var seq_time = 99999999999999
    var task = null
    for (var i in this.instance_list) {
      var current_task = this.instance_list[i]
      if (INSTANT_MESSAGE_TYPE.indexOf(current_task.type) < 0) {
        continue
      }
      if (!current_task.done) {
        if (current_task.seq_time < seq_time) {
          seq_time = current_task.seq_time
          task = current_task
          break
        }
      }
    }
    return task
  }
  onPageShow() {
    for (var i in this.task_list) {
      var c = this.task_list[i]
      if (c.doing) {
        c.done = true
        this.deleteDoneTask(c)
        break
      }
    }
  }
  deleteAllMaterials() {
    var _list = []
    for(var i in this.task_list) {
      var current = this.task_list[i]
      if (current.type !== Type.COMMON_TYPE.COMMON_LIVE_MATERIAL) {
        _list.push(current)
      }
    }
    this.task_list = _list
  }
}
module.exports = new MessageCenter()
